#pragma once

#include <list>
#include <algorithm>

class TimeQueue;

struct ITimeAware
{
	virtual void HandleEvent( unsigned long time, void* context) = 0;
};

struct TimeEntry
{
	unsigned long	eventTime;
	ITimeAware*		timeAware;
	void*			context;

	TimeEntry()
	{
	}
	TimeEntry( unsigned long et, ITimeAware* ta, void* ctxt )
		: eventTime(et), timeAware(ta), context(ctxt)
	{}
};

class TimeQueue
{
	std::list<TimeEntry> list1;
	std::list<TimeEntry> list2;
	std::list<TimeEntry>* current;
	std::list<TimeEntry>* next;

public:
	unsigned long currentTime;

public:
	TimeQueue();
	void Add( unsigned long eventTime, ITimeAware* pta, void* context );
	void Update( unsigned long curTime );
};

inline TimeQueue::TimeQueue()
{
	current = &list1;
	next    = &list2;
}

inline void TimeQueue::Add( unsigned long eventTime, ITimeAware* pta, void* context )
{
	next->push_back( TimeEntry(eventTime,pta,context) );
}

inline void TimeQueue::Update( unsigned long curTime )
{
	currentTime = curTime;

	std::for_each( current->begin(), current->end(),
		[&]( const TimeEntry& te ) {
			if ( te.eventTime > currentTime ) {
				next->push_back(te);
			}
			else {
				te.timeAware->HandleEvent( currentTime, te.context );
			}
	});

	current->resize(0); // need default contructor TimeEntry::TimeEntry()

	std::list<TimeEntry>* tmp = current;
	current = next;
	next = tmp;
}

